namespace C1.Win.C1FlexGrid
{
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Reflection;

    public class RowCollection : RowColCollection
    {
        internal int _maxNodeLevel;
        internal int _minNodeLevel;

        internal RowCollection(GridModel grid, int nItems, int nFixed, int defaultSize)
        {
            base._grid = grid;
            base._fixed = nFixed;
            base._frozen = 0;
            base._defaultSize = defaultSize;
            base._items = new ArrayList(nItems);
            for (int i = 0; i < nItems; i++)
            {
                base._items.Add(new Row(this));
            }
            base.SetDirty();
        }

        public Row Add()
        {
            return this.InsertInternal(base._items.Count, true, false);
        }

        public RowCollection GetSelection()
        {
            ArrayList list = new ArrayList();
            foreach (Row row in base._items)
            {
                if (row.Selected)
                {
                    list.Add(row);
                }
            }
            RowCollection rows = new RowCollection(base._grid, 0, 0, base._defaultSize);
            rows._items = list;
            return rows;
        }

        public Row Insert(int index)
        {
            return this.InsertInternal(index, true, false);
        }

        internal Row InsertInternal(int index, bool useDataSource, bool isNode)
        {
            if (useDataSource && base._grid.IsDataBound())
            {
                base._grid._dataSource.InsertAt(index - base._fixed);
                return this[index];
            }
            Row row = new Row(this);
            base._items.Insert(index, row);
            base.SetDirty();
            bool flag = false;
            for (Node node = row.Node; node != null; node = node.GetNode(NodeTypeEnum.Parent))
            {
                if (!node.Row.Visible || node.Collapsed)
                {
                    row._flags = (RowColFlags) ((short) (row._flags | RowColFlags.Hidden));
                    flag = true;
                    break;
                }
            }
            if (isNode)
            {
                row._flags = (RowColFlags) ((short) (row._flags | RowColFlags.IsNode));
                flag = true;
            }
            if (flag)
            {
                base.SetDirty();
            }
            base.NotifyViews(GridChangedTypeEnum.RowAdded, index, -1);
            return this[index];
        }

        public Node InsertNode(int index, int level)
        {
            Row row = this.InsertInternal(index, false, true);
            row._nodeLevel = (short) level;
            return row.Node;
        }

        public void InsertRange(int index, int count)
        {
            base._grid.AssertNotBound();
            for (int i = 0; i < count; i++)
            {
                base._items.Insert(index, new Row(this));
            }
            base.SetDirty();
            base.NotifyViews(GridChangedTypeEnum.RowAdded, index, -1);
        }

        public override void Move(int indexOld, int indexNew)
        {
            this.MoveInternal(indexOld, indexNew, true);
        }

        internal void MoveInternal(int indexOld, int indexNew, bool useDataSource)
        {
            if (useDataSource && base._grid.IsDataBound())
            {
                int dataIndex = this[indexOld].DataIndex;
                int num2 = this[indexNew].DataIndex;
                if ((dataIndex > -1) && (num2 > -1))
                {
                    base._grid._dataSource.Move(dataIndex, num2);
                    base.NotifyViews(GridChangedTypeEnum.RowMoved, indexOld, -1, indexNew, -1);
                    return;
                }
                if ((dataIndex > -1) || (num2 > -1))
                {
                    throw new ArgumentException("Invalid position for data row.");
                }
            }
            base.Move(indexOld, indexNew);
            base.NotifyViews(GridChangedTypeEnum.RowMoved, indexOld, -1, indexNew, -1);
        }

        public override void MoveRange(int index, int count, int indexNew)
        {
            base._grid.AssertNotBound();
            base.MoveRange(index, count, indexNew);
            base.NotifyViews(GridChangedTypeEnum.RowMoved, index, -1, indexNew, -1);
        }

        public Row Remove(int index)
        {
            return this.RemoveInternal(index, true);
        }

        internal Row RemoveInternal(int index, bool useDataSource)
        {
            Row row = this[index];
            if (row.IsNode)
            {
                row.Node.Collapsed = false;
            }
            if ((useDataSource && base._grid.IsDataBound()) && (row.DataIndex > -1))
            {
                base._grid._dataSource.RemoveAt(row.DataIndex);
                return (row.Detach() as Row);
            }
            base._items.RemoveAt(index);
            base.SetDirty();
            base.NotifyViews(GridChangedTypeEnum.RowRemoved, index, -1);
            return (row.Detach() as Row);
        }

        public void RemoveRange(int index, int count)
        {
            base._grid.AssertNotBound();
            for (int i = 0; i < count; i++)
            {
                ((RowCol) base._items[index]).Detach();
                base._items.RemoveAt(index);
            }
            base.SetDirty();
            base.NotifyViews(GridChangedTypeEnum.RowRemoved, index, -1);
        }

        internal void SetCount(int value)
        {
            this.SetCount(value, true);
        }

        internal void SetCount(int value, bool notify)
        {
            int count = base._items.Count;
            if (value > count)
            {
                if (base._items.Capacity < value)
                {
                    base._items.Capacity = value;
                }
                for (int i = count; i < value; i++)
                {
                    base._items.Add(new Row(this));
                }
                base.SetDirty();
                if (notify)
                {
                    base.NotifyViews(GridChangedTypeEnum.RowAdded);
                }
            }
            else if (value < count)
            {
                base._items.RemoveRange(value, count - value);
                base.SetDirty();
                if (notify)
                {
                    base.NotifyViews(GridChangedTypeEnum.RowRemoved);
                }
            }
        }

        internal override void Update()
        {
            if (base._dirty)
            {
                this._maxNodeLevel = -1;
                this._minNodeLevel = 0x7fffffff;
                int num = 0;
                int num2 = 0;
                int num3 = -base._fixed;
                foreach (Row row in base._items)
                {
                    row._index = num2++;
                    row._offset = num;
                    num += row.SizeDisplay;
                    if (((short) (row._flags & RowColFlags.IsNode)) != 0)
                    {
                        row._dataIndex = -1;
                        if (this._maxNodeLevel < row._nodeLevel)
                        {
                            this._maxNodeLevel = row._nodeLevel;
                        }
                        if (this._minNodeLevel > row._nodeLevel)
                        {
                            this._minNodeLevel = row._nodeLevel;
                        }
                        continue;
                    }
                    row._dataIndex = (num3 < 0) ? -1 : num3;
                    num3++;
                }
                base._dirty = false;
            }
        }

        [DefaultValue(50)]
        public override int Count
        {
            get
            {
                return base._items.Count;
            }
            set
            {
                if (base._items.Count != value)
                {
                    base._grid.AssertNotBound();
                    this.SetCount(value);
                }
            }
        }

        public override int Fixed
        {
            get
            {
                return base._fixed;
            }
            set
            {
                if (base._grid.IsDataBound())
                {
                    while (value > base._fixed)
                    {
                        base._fixed++;
                        this.InsertInternal(base._fixed - 1, false, false);
                    }
                    while (value < base._fixed)
                    {
                        base._fixed--;
                        this.RemoveInternal(base._fixed, false);
                    }
                }
                else
                {
                    base.Fixed = value;
                }
            }
        }

        public Row this[int index]
        {
            get
            {
                return (Row) base._items[index];
            }
        }
    }
}

